package com.itcast.www.im.ws;


import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Controller;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 使用@ServerEndpoint注解这个类以后
 * 我们可以把ChatEndPoint当成一个对讲机
 */
@Controller
@ServerEndpoint("/ws")
public class ChatEndPoint {

    private String name;
    private Session session;

    /**
     * 事件：连接成功 执行 onOpen方法
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        System.out.println("连接成功");
    }

    /**
     * 事件：连接关闭  执行onClose方法
     */
    @OnClose
    public void onClose() {
        if (this.name != null) {
            //this.name 下线了   如果功能很完善的话 我们需要周知  告诉所有在线人员某某某下线了
            ChatEndPointManager.del(this.name);
            List<ChatEndPoint> endPoints = ChatEndPointManager.getAllOnLines();

            Message msg = Message.getOffline(this.name);
            sendEndPointsMsg(endPoints, msg);
        }
        System.out.println("连接关闭");
    }

    /**
     * 事件：接收到消息    执行OnMessage方法
     *
     * @param meg 必须是json格式的字符串
     *            ->  '{"type":"login","loginName":"张三三","loginPass":"123"}'
     */
    @OnMessage
    public void OnMessage(String meg) {

        System.out.println(meg);
        //通过json工具转换成对象
        Message message = JSON.parseObject(meg, Message.class);

        if (message.getType().equals("login")) {
            //去做登陆操作
            doLogin(message);
        } else if (message.getType().equals("chat")) {
            //去处理聊天类型消息
            doChat(message);
        }
    }

    /**
     * 事件：发生错误异常  执行OnError方法
     *
     * @param e
     */
    @OnError
    public void OnError(Throwable e) {
        this.close();
        e.printStackTrace();
    }


    public void sendMessage(Message message) {
        //就会给当前终端对应的前端发送 信息
        try {
            this.session.getBasicRemote().sendText(JSON.toJSONString(message));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 给多个终端发送同一条消息
     *
     * @param list
     * @param msg
     */
    public void sendEndPointsMsg(List<ChatEndPoint> list, Message msg) {
        for (ChatEndPoint endPoint : list) {
            endPoint.sendMessage(msg);
        }
    }

    /**
     * 关闭连接
     */
    public void close() {
        try {
            this.session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 登录类型的消息处理
     *
     * @param message
     */
    public void doLogin(Message message) {

        //检查姓名和密码是否是真的  因为时间有限 不在查数据库
        //只要姓名长度为3  并且密码是123  就算登录成功
        if (message.getLoginName().length() == 3 && message.getLoginPass().equals("123")) {

            //如果客户登录成功 我们就可以给终端命名
            this.name = message.getLoginName();

            //先验证在线终端是否已经存在  存在就删除
            ChatEndPoint delEndPoint = ChatEndPointManager.del(this.name);
            //添加到在线终端
            ChatEndPointManager.add(this.name, this);
            message.setContent("登录成功");
            sendMessage(message);

            /**
             * 发送在线人员 给自己
             */
            sendOnLinesToSelf();

            //如果当前登录的人 是在线的中  就不在通知其他终端
            if (delEndPoint != null) {
                //delEndPoint不为空 ，说明这次登录的人 挤掉了前面同账号的人  需要把挤掉的这个人的终端关闭掉
                delEndPoint.close();
                return;
            }
            /**
             * 获取到其他终端以后  周知
             */
            List<ChatEndPoint> otherOnLines = ChatEndPointManager.getOtherOnLines(this.name);
            Message msg = Message.getOnline(this.name);
            sendEndPointsMsg(otherOnLines, msg);

        } else {
            message.setContent("登录失败");
            sendMessage(message);
        }

    }

    /**
     * 聊天类型信息处理
     *
     * @param message
     */
    public void doChat(Message message) {
        //通过 message 中toName找到你要聊天的人的终端机
        ChatEndPoint chatEndPoint = ChatEndPointManager.get(message.getToName());
        //发送消息
        chatEndPoint.sendMessage(message);
    }


    /**
     * 发送在线人员信息 给自己终端
     */
    public void sendOnLinesToSelf() {

        List<String> onLines = ChatEndPointManager.getOnLines();
        //把在线人列表 删除自己名字
        onLines.remove(this.name);
        Message onLineMessage = new Message();
        onLineMessage.setType("online");
        onLineMessage.setOnLines(onLines);
        sendMessage(onLineMessage);
    }

}
